#include "UdpServer.hpp"  // 包含UDP服务器类的头文件
#include <memory>         // 智能指针
#include <cstdio>         // 标准输入输出

// 打印使用说明函数
void Usage(std::string proc)
{
    // 告诉用户如何正确使用程序，要求输入大于1024的端口号
    std::cout << "\n\rUsage: " << proc << " port[1024+]\n" << std::endl;
}

// 消息处理函数，处理接收到的字符串
std::string Handler(const std::string &str)
{
    // 构建响应消息
    std::string res = "Server get a message: ";
    res += str;
    std::cout << res << std::endl;

    /* 注释掉的进程创建代码
    // fork()创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        // 在子进程中可以执行其他程序
        // 例如执行 ls -a -l 命令
        // 可以使用exec族函数
    }
    */
    return res;
}

// 执行shell命令并获取执行结果的函数
std::string ExcuteCommand(const std::string &cmd)
{
    // TODO: 添加安全检查机制
    // SafeCheck(cmd);

    // popen()创建管道，执行命令，并返回文件指针
    // "r"表示我们要读取命令的输出
    FILE *fp = popen(cmd.c_str(), "r");
    if(nullptr == fp)
    {
        perror("popen");  // 如果popen失败，打印错误信息
        return "error";
    }

    // 读取命令执行结果
    std::string result;
    char buffer[4096];  // 临时缓冲区
    while(true)
    {
        // 从管道读取数据到缓冲区
        char *ok = fgets(buffer, sizeof(buffer), fp);
        if(ok == nullptr) break;  // 如果读取完毕或出错，退出循环
        result += buffer;         // 将读取的数据追加到结果字符串
    }
    pclose(fp);  // 关闭管道

    return result;
}

// 主函数
// ./udpserver port
int main(int argc, char *argv[])
{
    // 检查命令行参数数量是否正确
    if(argc != 2)
    {
        Usage(argv[0]);  // 如果参数数量不对，打印使用说明
        exit(0);         // 退出程序
    }

    // 将命令行参数（端口号）转换为整数
    uint16_t port = std::stoi(argv[1]);

    // 创建UDP服务器对象，使用智能指针管理
    std::unique_ptr<UdpServer> svr(new UdpServer(port));

    // 初始化服务器
    svr->Init(/**/);
    
    // 运行服务器，传入命令执行函数作为回调
    svr->Run(ExcuteCommand);

    return 0;
}